#include<iostream>
#include<random>
#include<vector>
#include<Windows.h>

//取消其他工程文件内的min max宏定义
#undef min
#undef max 

#define min *p
#define max *(p+1)
#define times *(p+2)
#define array p
#define length max-min+1

using std::cin;
using std::cout;
using std::endl;
using std::shuffle;
using std::vector;
using std::uniform_int_distribution;
using std::default_random_engine;
using std::shuffle;

void getRandNum(int* p);
void setNum(int* p);
bool checkInput();
bool checkIsOver();
void newLine();
void choice();

//===========初始化===========//
bool IsOver = false;	//程序结束判断符
int* p = new int[3];	//为用户输入的数据分配空间
int choices;		//定义走向标识符
enum allChoices {
	chsBegin = 1,
	chsEnd
};
//===========================//

int main() {
	while (!IsOver) {
		choice();
		IsOver = checkIsOver();
	}
	delete[] p;			//释放内存
	return 0;
}

//依照用户输入的数据取得随机数 随机数不可重复
void getRandNum(int* p) {
	vector<int> numGroup;
	default_random_engine e((unsigned int)time(0));
	for (int j = 0; j <= max - min; j++) {
		numGroup.push_back(min + j);
	}
	shuffle(numGroup.begin(),numGroup.end(),e);
	cout << endl;
	for (int i = 0; i < times; i++) {
		cout << "\t" << numGroup[i];
		if ((i + 1) % 8 == 0)
			cout << endl << endl << endl;
	}
	cout << endl;
}

//按用户要求输出随机数 随机数可重复
void getRandNum2(int* p) {
	uniform_int_distribution<int> u(min,max);		//括号内为范围 为闭区间
	default_random_engine e((unsigned int)time(0));
	newLine();
	for (int i = 1; i <= times; i++) {		//i为伪随机数个数
		cout << "\t" << u(e);
		if (i % 8 == 0)					//每8个数换行
			cout << endl << endl << endl;
	}
	newLine();
}

//记录用户输入数据
void setNum(int* p) {	
	while (true) {
		cout << "提示:所输入范围为闭区间";
		if (choices == 1)
			cout << "----不可重复随机数" << endl;
		else
			cout << "----可重复随机数" << endl;
		do {
			cout << "请输入最小值:";
			cin >> min;
		} while (!checkInput());
		do {
			cout << "请输入最大值:";
			cin >> max;
		} while (!checkInput());
		do {
			cout << "请输入随机数个数:";
			cin >> times;
		} while (!checkInput());
		if (min > max) {		//若最小值大于最大值或者取出随机数个数大于数组长度抛出异常
			system("cls");
			cout << "Error!最小值不能大于最大值!" << endl;
		}
		else if (choices == 1 && length < times) {
			system("cls");
			cout << "Error!取得随机数个数不能大于设定区间元素总数!" << endl;
		}
		else
			break;
	}
	return;
}

//检查输入是否正确
bool checkInput() {
	if (cin.fail()) {
		cout << "输入数据有误!请重新输入!" << endl;
		cin.clear();		//将判断符重置
		while (cin.get() != '\n');		//清除缓冲区内所有字符
		return false;
	}
	else
		return true;
}

//判断程序是否结束
bool checkIsOver() {
	char temp;
	newLine();
	cout << "是否继续输入?(是：y,否:n):";
	for (;;) {
		cin >> temp;
		if (temp == 'y') {
			system("cls");
			return false;
		}
		else if (temp == 'n')
			return true;
		else {
			cout << "输入数据有误!请重新输入:";
			while (cin.get() != '\n');
		}
	}
}

//换行用
void newLine() {
	cout << endl;
}

//根据用户输入数判断走向
void choice() {
	cout << "欢迎进入随机数小程序!" << endl;
	cout << "1.随机数(不可取重复值)" << endl;
	cout << "2.随机数(可取重复值)" << endl;
	for (;;) {
		cout << "请输入:";
		cin >> choices;
		if (chsBegin <= choices && choices <= chsEnd)
			break;
		else
			cout << "输入数据有误!请重新输入!" << endl;
	}
	setNum(array);
	system("cls");
	for(;;){
		switch (choices) {
		case 1: {
			getRandNum(array);
		}goto outtaloop;
		case 2: {
			getRandNum2(array);
		}goto outtaloop;
		default: {
			cout << "输入数据有误!请重新输入!" << endl;
			Sleep(2000);
		}break;
		}
	}
outtaloop:;
}